// src/kyc/kyc.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as crypto from 'crypto';

@Injectable()
export class KycService {
    private readonly appToken?: string;
    private readonly secretKey?: string;
    private readonly baseUrl: string;
    private readonly levelName: string;

    constructor(private configService: ConfigService) {
        this.appToken = this.configService.get<string>('SUMSUB_APP_TOKEN');
        this.secretKey = this.configService.get<string>('SUMSUB_SECRET_KEY');
        if (!this.appToken || !this.secretKey) {
            throw new Error('Sumsub app token or secret key is not configured');
        }
        this.baseUrl = this.configService.get<string>('SUMSUB_BASE_URL', 'https://api.sumsub.com');
        this.levelName = this.configService.get<string>('SUMSUB_LEVEL_NAME', 'id-and-liveness');
    }

    async createApplicant(userId: string): Promise<any> {
        const timestamp = Math.floor(Date.now() / 1000);

        const requestBody = {
            externalUserId: userId,
        };

        const url = `/resources/applicants?levelName=${encodeURIComponent(this.levelName)}`;
        const signature = this.generateSignature(timestamp, requestBody, 'POST', url);

        const response = await fetch(`${this.baseUrl}${url}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-App-Token': this.appToken!,
                'X-App-Access-Ts': timestamp.toString(),
                'X-App-Access-Sig': signature,
            },
            body: JSON.stringify(requestBody),
        });

        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Sumsub API error: ${response.status} ${response.statusText} - ${errorText}`);
        }

        return await response.json();
    }

    async generateAccessToken(userId: string): Promise<string> {
        const timestamp = Math.floor(Date.now() / 1000);

        // 构建请求体
        const requestBody = {
            userId: userId,
            levelName: this.levelName,
            ttlInSecs: 600,
        };

        // 使用实际请求体生成签名
        const signature = this.generateSignature(timestamp, requestBody);

        const response = await fetch(`${this.baseUrl}/resources/accessTokens/sdk`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-App-Token': this.appToken!,
                'X-App-Access-Ts': timestamp.toString(),
                'X-App-Access-Sig': signature,
            },
            body: JSON.stringify(requestBody),
        });

        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Sumsub API error: ${response.status} ${response.statusText} - ${errorText}`);
        }

        const data = await response.json();
        return data.token;
    }

    async getApplicantStatus(userId: string): Promise<any> {
        const timestamp = Math.floor(Date.now() / 1000);
        const url = `/resources/applicants/-;externalUserId=${encodeURIComponent(userId)}/status`;

        // 生成签名（GET 请求不需要请求体）
        const signature = this.generateSignature(timestamp, null, 'GET', url);

        const response = await fetch(`${this.baseUrl}${url}`, {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'X-App-Token': this.appToken!,
                'X-App-Access-Ts': timestamp.toString(),
                'X-App-Access-Sig': signature,
            },
        });

        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Sumsub API error: ${response.status} ${response.statusText} - ${errorText}`);
        }

        return await response.json();
    }

    async getApplicantInfo(userId: string): Promise<any> {
        const timestamp = Math.floor(Date.now() / 1000);
        const url = `/resources/applicants/-;externalUserId=${encodeURIComponent(userId)}/one`;

        // 生成签名（GET 请求不需要请求体）
        const signature = this.generateSignature(timestamp, null, 'GET', url);

        const response = await fetch(`${this.baseUrl}${url}`, {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'X-App-Token': this.appToken!,
                'X-App-Access-Ts': timestamp.toString(),
                'X-App-Access-Sig': signature,
            },
        });

        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Sumsub API error: ${response.status} ${response.statusText} - ${errorText}`);
        }

        return await response.json();
    }

    async getApplicantChecks(userId: string): Promise<any> {
        const timestamp = Math.floor(Date.now() / 1000);
        const url = `/resources/applicants/-;externalUserId=${encodeURIComponent(userId)}/checks`;

        // 生成签名（GET 请求不需要请求体）
        const signature = this.generateSignature(timestamp, null, 'GET', url);

        const response = await fetch(`${this.baseUrl}${url}`, {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'X-App-Token': this.appToken!,
                'X-App-Access-Ts': timestamp.toString(),
                'X-App-Access-Sig': signature,
            },
        });

        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Sumsub API error: ${response.status} ${response.statusText} - ${errorText}`);
        }

        return await response.json();
    }

    private generateSignature(timestamp: number, requestBody: any, method: string = 'POST', url: string = '/resources/accessTokens/sdk'): string {
        let bodyString = '';
        if (requestBody) {
            bodyString = JSON.stringify(requestBody);
        }

        // Sumsub 签名格式: timestamp + method + url + body
        const data = timestamp + method.toUpperCase() + url + bodyString;

        return crypto
            .createHmac('sha256', this.secretKey!)
            .update(data)
            .digest('hex');
    }
}